package starfield.modpack;

import starfield.modpack.web.WebModpack;
import java.awt.Color;
import java.io.File;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import starfield.modpack.web.SyncingProtocol;
import starfield.ValidationException;

public class WebModpackDialog extends javax.swing.JDialog {

	private boolean hasAnswered;
	private WebModpack modpack;
	
	private WebModpackDialog(java.awt.Frame parent, boolean modal) {
		super(parent, modal);
        setLocationRelativeTo(parent);
		initComponents();
	}
	
	public static WebModpackDialog show(java.awt.Frame parent, boolean modal) {
		WebModpackDialog webModpackDialog = new WebModpackDialog(parent, modal);
		webModpackDialog.setTitle("New web modpack");
        webModpackDialog.setVisible(true);
		return webModpackDialog;
	}
	
	public static WebModpackDialog show(java.awt.Frame parent, boolean modal, WebModpack modpack) {
		WebModpackDialog webModpackDialog = new WebModpackDialog(parent, modal);
		webModpackDialog.setTitle("Edit web modpack '" + modpack.getName()+ "'");
		webModpackDialog.fillFromModpack(modpack);
        webModpackDialog.setVisible(true);
		return webModpackDialog;
	}
	
	public void validateModpack() throws ValidationException {
		getDirectoryName();
		getHostname();
		getProtocol();
		getPort();
		getRequiresLogin();
		getUsername();
		getPassword();
	}
	
	public void fillModpack(WebModpack modpack) throws ValidationException {
		modpack.setHostname(getHostname());
		modpack.setProtocol(getProtocol());
		modpack.setPort(getPort());
		modpack.setRequiresLogin(getRequiresLogin());
		modpack.setUsername(getUsername());
		modpack.setPassword(getPassword());
	}
	
	public void fillFromModpack(WebModpack modpack) {
		this.modpack = modpack;
		setHostname(modpack.getHostname());
		setDirectoryName(modpack.getName());
		setProtocol(modpack.getProtocol());
		setPort(modpack.getPort());
		setRequiresLogin(modpack.requiresLogin());
		setUsername(modpack.getUsername());
		setPassword(modpack.getPassword());
	}
	
	public String getDirectoryName() throws ValidationException {
		validateDirectoryName();
		
		return directoryField.getText();
	}
	
	public void setDirectoryName(String directoryName) {
		directoryField.setText(directoryName);
	}
	
	public String getHostname() {
		return hostnameField.getText();
	}
	
	public void setHostname(String hostname) {
		hostnameField.setText(hostname);
	}
	
	public SyncingProtocol getProtocol() throws ValidationException {
		try {
			return SyncingProtocol.valufOfIgnoreCase(protocolField.getSelectedItem().toString());
		} catch (IllegalArgumentException ex) {
			throw new ValidationException("Invalid protocol.");
		}
	}
	
	public void setProtocol(SyncingProtocol protocol) {
		for (int i = 0; i < protocolField.getItemCount(); i++) {
			if (protocol.name().equalsIgnoreCase(protocolField.getItemAt(i).toString())) {
				protocolField.setSelectedIndex(i);
				return;
			}
		}
		
		JOptionPane.showMessageDialog(
				this, 
				"Unknown protocol '" + protocol + "'.", 
				"Starfield", 
				JOptionPane.WARNING_MESSAGE);
	}
	
	public int getPort() throws ValidationException {
		try {
			return Integer.parseInt(portField.getText());
		} catch (NumberFormatException ex) {
			throw new ValidationException("Invalid port.", ex);
		}
	}
	
	public void setPort(int port) {
		portField.setText(Integer.toString(port));
	}
	
	public boolean getRequiresLogin() {
		return requiresLoginCheckBox.isSelected();
	}
	
	public void setRequiresLogin(boolean requiresLogin) {
		requiresLoginCheckBox.setSelected(requiresLogin);
	}
	
	public String getUsername() {
		if (getRequiresLogin()) {
			return usernameField.getText();
		} else {
			return null;
		}
	}
	
	public void setUsername(String username) {
		usernameField.setText(username);
	}
	
	public String getPassword() {
		if (getRequiresLogin()) {
			return passwordField.getText();
		} else {
			return null;
		}
	}
	
	public void setPassword(String password) {
		passwordField.setText(password);
	}
	
	public boolean hasAnswered() {
		return hasAnswered;
	}
		private String getNewDirectoryName() {
		return directoryField.getText();
	}
	
	private String getOldDirectoryName() {
		return modpack != null ? modpack.getName() : null;
	}
	
	public boolean hasDirectoryNameChanged() {
		return !getNewDirectoryName().equals(getOldDirectoryName());
	}
	
	private void validateDirectoryName() throws ValidationException {
		String newDirectoryName = getNewDirectoryName();
		File newDirectory = new File(Modpack.getDirectoryPath(newDirectoryName));
		
		if (hasDirectoryNameChanged()) {
			if (newDirectoryName.length() == 0) {
				throw new ValidationException("The directory name cannot be empty.");
			}
			
			if (newDirectory.exists() && newDirectory.isDirectory()) {
				throw new ValidationException("The directory already exists.");
			}
			
			if (!Modpack.ensureDirectoryName(newDirectoryName)) {
				throw new ValidationException("The directory name contains invalid characters.");
			}
		}
	}
	
	private void directoryFieldTextChanged(javax.swing.event.DocumentEvent evt) {
		String error = null;

		try {
			validateDirectoryName();
		} catch (ValidationException vex) {
			error = vex.getMessage();
		}

		if (error == null) {
			directoryStateLabel.setIcon(new ImageIcon(getClass().getResource("/starfield/icons/tick.png")));
			directoryStateLabel.setForeground(Color.decode("#006400"));

			if (!hasDirectoryNameChanged()) {
				directoryStateLabel.setText("The directory has not changed.");
			} else {
				directoryStateLabel.setText("This is a valid directory!");
			}
		} else {
			directoryStateLabel.setIcon(new ImageIcon(getClass().getResource("/starfield/icons/cross.png")));
			directoryStateLabel.setForeground(Color.decode("#8B0000"));
			directoryStateLabel.setText(error);
		}
	}

	@SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        directoryLabel = new javax.swing.JLabel();
        directoryPrefixLabel = new javax.swing.JLabel();
        directoryField = new javax.swing.JTextField();
        directoryStateLabel = new javax.swing.JLabel();
        protocolLabel = new javax.swing.JLabel();
        protocolField = new javax.swing.JComboBox();
        portLabel = new javax.swing.JLabel();
        portField = new javax.swing.JTextField();
        hostnameLabel = new javax.swing.JLabel();
        hostnameField = new javax.swing.JTextField();
        requiresLoginCheckBox = new javax.swing.JCheckBox();
        usernameLabel = new javax.swing.JLabel();
        usernameField = new javax.swing.JTextField();
        passwordLabel = new javax.swing.JLabel();
        passwordField = new javax.swing.JTextField();
        okButton = new javax.swing.JButton();
        cancelButton = new javax.swing.JToggleButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setMinimumSize(new java.awt.Dimension(265, 223));
        setResizable(false);

        directoryLabel.setText("Directory:");

        directoryPrefixLabel.setForeground(javax.swing.UIManager.getDefaults().getColor("textInactiveText"));
        directoryPrefixLabel.setText("modpacks/");

        directoryField.getDocument().addDocumentListener(new javax.swing.event.DocumentListener() {
            public void changedUpdate(javax.swing.event.DocumentEvent evt) {
                directoryFieldTextChanged(evt);
            }
            public void removeUpdate(javax.swing.event.DocumentEvent evt) {
                directoryFieldTextChanged(evt);
            }
            public void insertUpdate(javax.swing.event.DocumentEvent evt) {
                directoryFieldTextChanged(evt);
            }
        });

        directoryStateLabel.setText(" ");

        protocolLabel.setText("Protocol:");

        protocolField.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "FTP", "FTPS", "FTPES", "HTTP" }));
        protocolField.removeAllItems();

        for (SyncingProtocol protocol : SyncingProtocol.values()) {
            protocolField.addItem(protocol.name());
        }
        protocolField.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                protocolFieldActionPerformed(evt);
            }
        });
        protocolField.setSelectedIndex(0);

        portLabel.setText("Port:");

        hostnameLabel.setText("Hostname:");

        requiresLoginCheckBox.setText("Login required");
        requiresLoginCheckBox.setMargin(new java.awt.Insets(2, 0, 2, 2));
        requiresLoginCheckBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                requiresLoginCheckBoxItemStateChanged(evt);
            }
        });

        usernameLabel.setText("Username:");
        usernameLabel.setEnabled(false);

        usernameField.setEnabled(false);

        passwordLabel.setText("Password:");
        passwordLabel.setEnabled(false);

        passwordField.setEnabled(false);

        okButton.setText("OK");
        okButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                okButtonActionPerformed(evt);
            }
        });

        cancelButton.setText("Cancel");
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addComponent(okButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(cancelButton))
                    .addGroup(layout.createSequentialGroup()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(hostnameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)
                            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(protocolLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)
                                    .addComponent(directoryLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE))
                                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                                    .addComponent(passwordLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)
                                    .addComponent(usernameLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE))))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(requiresLoginCheckBox)
                                .addGap(0, 0, Short.MAX_VALUE))
                            .addComponent(usernameField)
                            .addComponent(directoryStateLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(directoryPrefixLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(directoryField))
                            .addGroup(layout.createSequentialGroup()
                                .addComponent(protocolField, 0, 200, Short.MAX_VALUE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(portLabel)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(portField, javax.swing.GroupLayout.PREFERRED_SIZE, 43, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addComponent(passwordField, javax.swing.GroupLayout.Alignment.TRAILING)
                            .addComponent(hostnameField))))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(directoryField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(directoryLabel)
                    .addComponent(directoryPrefixLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(directoryStateLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(hostnameLabel)
                    .addComponent(hostnameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(protocolLabel)
                    .addComponent(portLabel)
                    .addComponent(portField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(protocolField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(requiresLoginCheckBox)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(usernameLabel)
                    .addComponent(usernameField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(passwordLabel)
                    .addComponent(passwordField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(cancelButton)
                    .addComponent(okButton))
                .addContainerGap())
        );

        pack();
        setLocationRelativeTo(null);
    }// </editor-fold>//GEN-END:initComponents

    private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
        try {
            validateModpack();
            hasAnswered = true;
            setVisible(false);
        } catch (ValidationException vex) {
            JOptionPane.showMessageDialog(this, vex.getMessage(), "Modpack validation", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_okButtonActionPerformed

    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
        hasAnswered = false;
        setVisible(false);
    }//GEN-LAST:event_cancelButtonActionPerformed

    private void protocolFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_protocolFieldActionPerformed
		try {
			setPort(getProtocol().getPort());
		} catch (ValidationException ex) {
			portField.setText(null);
		}
    }//GEN-LAST:event_protocolFieldActionPerformed

    private void requiresLoginCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_requiresLoginCheckBoxItemStateChanged
		boolean enabled = getRequiresLogin();
		
		usernameLabel.setEnabled(enabled);
		usernameField.setEnabled(enabled);
		passwordLabel.setEnabled(enabled);
		passwordField.setEnabled(enabled);
    }//GEN-LAST:event_requiresLoginCheckBoxItemStateChanged


    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JToggleButton cancelButton;
    private javax.swing.JTextField directoryField;
    private javax.swing.JLabel directoryLabel;
    private javax.swing.JLabel directoryPrefixLabel;
    private javax.swing.JLabel directoryStateLabel;
    private javax.swing.JTextField hostnameField;
    private javax.swing.JLabel hostnameLabel;
    private javax.swing.JButton okButton;
    private javax.swing.JTextField passwordField;
    private javax.swing.JLabel passwordLabel;
    private javax.swing.JTextField portField;
    private javax.swing.JLabel portLabel;
    private javax.swing.JComboBox protocolField;
    private javax.swing.JLabel protocolLabel;
    private javax.swing.JCheckBox requiresLoginCheckBox;
    private javax.swing.JTextField usernameField;
    private javax.swing.JLabel usernameLabel;
    // End of variables declaration//GEN-END:variables
}
